package com.cabinet.ui;

import com.cabinet.Config;
import com.cabinet.Device;
import com.cabinet.db.DBDeviceState;
import com.cabinet.db.DBLocation;
import com.cabinet.db.DBLocations;

import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.*;
import java.util.*;

/**
* Created by IntelliJ IDEA.
* User: denny
* Date: 10/2/13
* Time: 6:50 PM
* To change this template use File | Settings | File Templates.
*/
abstract class ClassPanel extends JPanel {
  abstract void saveDeviceStates();
  abstract void showConfigManager();
  abstract boolean isMovingDevices();
  abstract java.util.List<String> allConfigNames();
  abstract void configurationSelected(int row);
  abstract void devicesConfigChanged();
  abstract void refreshConfigurationView();



  //Map<Long, JList> conferenceLists = new HashMap<>();
  JComboBox<String> configDDOptions = new JComboBox<String>();
  java.util.Map<Long,DevicePanel> devicePanels = new HashMap<>();

  boolean portActivated=false;
  JButton btnActivate = new JButton("Активувати");


  JPanel bottomConferences = new JPanel(new FlowLayout(FlowLayout.LEFT, 0,0));

  static final DataFlavor dragDropObjectFlavor;

  static{
    dragDropObjectFlavor = new ActivationDataFlavor(
        Long[].class, DataFlavor.javaJVMLocalObjectMimeType, "Array of items");
  }

  JMenuItem speakAll = new JMenuItem("Включити всі мікрофони");
  JMenuItem speakAllNot = new JMenuItem("Виключити всі мікрофони");
  JPopupMenu groupPopupMenu = new JPopupMenu();



  ClassPanel() {
    super(new BorderLayout());
    JPanel classPanel = this;
    classPanel.add(topButtons(), BorderLayout.NORTH);
   // classPanel.add(rightColumn(), BorderLayout.EAST);
    classPanel.add(centerPanel(), BorderLayout.CENTER);
//    bottomConferences.setMinimumSize(new Dimension(50,50));
//    bottomConferences.setBorder(BorderFactory.createLineBorder(Color.RED,4));
    groupPopupMenu.add(speakAll);
    groupPopupMenu.add(speakAllNot);

    speakAll.addActionListener(new GroupSwitch(true));
    speakAllNot.addActionListener(new GroupSwitch(false));

  }

  class GroupSwitch implements ActionListener{
    boolean on;

    GroupSwitch(boolean on) {
      this.on = on;
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
      for( DevicePanel dp : devicePanels.values() ){
        if( dp.groupSelected ){
          dp.speak.setSelected( on );
          dp.switchChange(dp.speak);
        }
      }
    }
  }

  void refreshView(){
    configDDOptions.removeAllItems();
    for( String c : allConfigNames() ){
      configDDOptions.addItem(c);
    }
    refreshConfigurationView();
  }


//  void gridBagAddPair(JPanel p, JComponent c1, JComponent c2){
//    c1.setBorder(new LineBorder(Color.BLACK, 1));
//    c2.setBorder(new LineBorder(Color.BLACK, 1));
//    GridBagConstraints con1 = new GridBagConstraints();
//    con1.fill = GridBagConstraints.BOTH;
//    p.add(c1, con1);
//    GridBagConstraints con2 = new GridBagConstraints();
//    con2.gridwidth = GridBagConstraints.REMAINDER;
//    con2.fill = GridBagConstraints.BOTH;
//    p.add(c2, con2);
//
//  }
//
//  void listDragSupport(final JList list){
//    list.setTransferHandler(new ListItemTransferHandler());
//    list.setDropMode(DropMode.INSERT);
//    list.setDragEnabled(true);
//  }


  JPanel centerPanel(){
   // JPanel p = new JPanel();
    //p.setMaximumSize(new Dimension(300, 1000));
    //p.setBorder(new LineBorder(Color.GREEN, 3));
  //  p.setLayout(new GridBagLayout());

//    gridBagAddPair(p, new JLabel("Конференції"), new JLabel("Учасники"));
//
//    JList<String> l = new JList<String>(new DefaultListModel<String>());
//    listDragSupport(l);
//
//
//    JLabel lab0 = new JLabel("Відключені");
//    lab0.setOpaque(true);
//    lab0.setBackground(Color.decode("0xff0000")/* Color.GREEN.brighter()*/);
//    lab0.setVerticalAlignment(SwingConstants.TOP);
//    gridBagAddPair(p, lab0, l);
//    conferenceLists.put(-1L, l);
//
//    ArrayList<String> rowNames = new ArrayList<>();
//    for( int i=1; i<=8; i++ ){
//      rowNames.add("Конференція "+i);
//    }
//    rowNames.add("Вчительська конференція");

//    long confId=0;
//    for( String rn : rowNames ){
//      JList<String> li = new JList<String>(new DefaultListModel<String>());
//      listDragSupport(li);
//
//      JLabel labi = new JLabel(rn);
//      labi.setVerticalAlignment(SwingConstants.TOP);
//      gridBagAddPair(p, labi, li);
//      conferenceLists.put(confId, li);
//      confId++;
//    }


    JPanel center = new JPanel();
    center.setLayout(new BorderLayout());

    //JPanel right = new JPanel();
    //right.setLayout(new BorderLayout());
  //  right.setLayout(null); // hide original version conference text lists
 //   p.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
 //   right.add(p, BorderLayout.NORTH); //- old original version conference text lists

    JPanel locationsPanel = makeLocationsPanel();
    center.add(locationsPanel, BorderLayout.CENTER);
 //   center.add(right, BorderLayout.EAST);
    center.add(bottomConferences, BorderLayout.SOUTH);
    bottomConferences.setBackground(Color.WHITE);

//    JList<String> list = new JList<String>(new String[]{"11111111111","2222222222","33333333"});
//    list.setTransferHandler(new ListItemTransferHandler());
//    list.setDropMode(DropMode.INSERT);
//    list.setDragEnabled(true);
//    center.add(list, BorderLayout.WEST);

    locationsPanel.addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        groupDeselectAll();
      }
    });



    return center;
  }

  public static final long CONFERENCE_SELF_TEST = 9;

  Map<Long,java.util.List<DBDeviceState>> groupByConference(Collection<DBDeviceState> dbDevices){
    Map<Long,java.util.List<DBDeviceState>> ret = new HashMap<>();
    for( DBDeviceState st : dbDevices ){
      long conf = st.getConferenceId();
      if( st.isSelfTest() ){
        conf = CONFERENCE_SELF_TEST;
      }
      java.util.List<DBDeviceState> set = ret.get(conf);
      if( set==null ){
        set = new ArrayList<>();
        ret.put(conf, set);
      }
      set.add(st);
    }
    return ret;
  }

  Comparator<DBDeviceState> cmpConferenceDevs = new Comparator<DBDeviceState>(){
    @Override
    public int compare(DBDeviceState d1, DBDeviceState d2) {
      return ord(d1).compareTo(ord(d2));
    }

    Long ord(DBDeviceState d){
      if( d.getDevId()==Device.TEACHER ){
        return -100L;
      }
      if( Device.isAudioDevice(d.getDevId()) ){
        return -50 + d.getDevId();
      }
      return d.getDevId();
    }
  };

        /*
  JPanel rightColumn(){
    JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(0,1));
    //panel.setLayout(new FlowLayout());
    for( int i=1; i<=16; i++ ){
      JLabel box = new JLabel(" ");
      box.setOpaque(true);
      box.setBackground(Color.GREEN);
      box.setPreferredSize(new Dimension(10,10));
      panel.add(box);
      panel.add(new JLabel(""+i));
    }

    JPanel right = new JPanel();
    right.setLayout(new FlowLayout());
    right.add(panel);
    return right;
  }
   */

  JPanel topButtons(){
    JPanel p = new JPanel();
    p.setLayout(new FlowLayout());

    JButton btnMngrConfig = new JButton("Менеджер конфігурацій");
    btnMngrConfig.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        showConfigManager();
      }
    });

    //btnActivate.setEnabled(false);
    JButton btnAnnounce = new JButton("Зробити об’яву");
    btnAnnounce.setEnabled(false);
    JButton btnSave = new JButton("Зберегти");

    btnSave.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        saveDeviceStates();
      }
    });

    configDDOptions.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        configurationSelected(configDDOptions.getSelectedIndex());
      }
    });

    p.add(configDDOptions);
    p.add(btnMngrConfig);
    p.add(btnActivate);
    p.add(btnAnnounce);
    p.add(btnSave);

    return p;
  }

  /*
  class ListItemTransferHandler extends TransferHandler {

    private Object[] transferedObjects = null;
    public ListItemTransferHandler() {
    }
    @SuppressWarnings("deprecation")
    @Override protected Transferable createTransferable(JComponent c) {
      JList list = (JList) c;
      transferedObjects = list.getSelectedValues();
      return new DataHandler(transferedObjects, dragDropObjectFlavor.getMimeType());
    }
    @Override public boolean canImport(TransferSupport info) {
      if(!info.isDrop() || !info.isDataFlavorSupported(dragDropObjectFlavor)) {
        return false;
      }

      JList target = (JList)info.getComponent();
      DefaultListModel listModel = (DefaultListModel)target.getModel();
      try {
        Object[] values = (Object[])info.getTransferable().getTransferData(dragDropObjectFlavor);
        for( Object o : values ){
          if( listModel.contains(o) ){
            return false;
          }
        }
        return true;
      } catch(UnsupportedFlavorException ufe) {
        ufe.printStackTrace();
      } catch(IOException ioe) {
        ioe.printStackTrace();
      }


      return false;
    }
    @Override public int getSourceActions(JComponent c) {
      return MOVE; //TransferHandler.COPY_OR_MOVE;
    }
    @SuppressWarnings("unchecked")
    @Override public boolean importData(TransferSupport info) {
      if(!canImport(info)) {
        return false;
      }
      JList target = (JList)info.getComponent();
      JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
      DefaultListModel listModel = (DefaultListModel)target.getModel();
      int index = dl.getIndex();
      int max = listModel.getSize();
      if(index<0 || index>max) {
        index = max;
      }
      try {
        java.util.List<Long> values = (java.util.List<Long>)info.getTransferable().getTransferData(dragDropObjectFlavor);
        for(int i=0; i<values.size(); i++) {
          int idx = index++;
          listModel.add(idx, values[i]);
          target.addSelectionInterval(idx, idx);
        }
        cleanupOtherlistsAfterDragDrop(target, values);
        devicesConfigChanged();
        return true;
      } catch(UnsupportedFlavorException ufe) {
        ufe.printStackTrace();
      } catch(IOException ioe) {
        ioe.printStackTrace();
      }

      return false;
    }
    @Override protected void exportDone(
        JComponent c, Transferable data, int action) {
      //cleanup(c, action == MOVE);
    }
//    private void cleanup(JComponent c, boolean remove) {
//      if(remove && transferedObjects != null) {
//        JList source = (JList)c;
//        DefaultListModel model = (DefaultListModel)source.getModel();
//        for(Object string : transferedObjects) {
//          model.removeElement(string);
//        }
//      }
//      transferedObjects=null;
//    }
  }
  */

  JPanel makeLocationsPanel(){
    JPanel p = new JPanel();
    p.setOpaque(true);
    p.setBackground(Color.WHITE);
    //p.setBackground(Color.BLUE.darker());
    //p.setBackground(new Color(234, 255, 9));
    p.setLayout(null);

    DBLocations dbLocations = null;
    try {
      dbLocations = DBLocations.loadFromDiskDB();
    } catch (Exception e) {
      e.printStackTrace();
    }

    Set<Integer> visibleStudents = Config.getVisibleStudents();
    Set<Integer> visibleAudio = Config.getVisibleAudio();
    for( Device d : Device.all() ){
      DevicePanel dev = new ActiveDevicePanel(d.getId());
      devicePanels.put(d.getId(), dev);
      int x = (int)(Math.random()*700);
      int y = (int)(Math.random()*500);
      
      if( dbLocations!=null ){
        DBLocation loc = dbLocations.findByDevId(d.getId());
        if( loc!=null ){
          x = loc.getX();
          y = loc.getY();
        }
      }
      
      //dev.setBounds(x,y,140,60);
      //dev.setBounds(x,y,200,100);
      dev.setBounds(x,y,DevicePanel.TOTAL_W,DevicePanel.TOTAL_H);
      if( Device.isStudent(d.getId()) ){
        if( visibleStudents.contains((int)(d.getId()+1)) ){
          p.add(dev);
        }
      } else if( Device.isAudioDevice(d.getId()) ){
        if( visibleAudio.contains((int)Device.audioDevNumber(d.getId())) ){
          p.add(dev);
        }
      } else {
        p.add(dev);
      }

    }

    new SelectionRectangle(p);

    return p;
  }

  class ActiveDevicePanel extends DevicePanel{


    @Override
    void devicesConfigChanged() {
      ClassPanel.this.devicesConfigChanged();
    }

    ActiveDevicePanel(final long devId) {
      super(devId);

      setTransferHandler(new TransferHandler("devId") {
        @Override
        protected Transferable createTransferable(JComponent c) {
          //return new DataHandler(new Object[]{getDeviceName()}, dragDropObjectFlavor.getMimeType());
          Long[] sel;
          if( groupSelected ){
            sel = groupSelectedIds();
          }else{
            sel = new Long[]{devId};
          }
          return new DataHandler(sel, dragDropObjectFlavor.getMimeType());
        }
      });

      MouseListener ml = new MouseAdapter(){
        public void mousePressed(MouseEvent e){
          if( Config.right(e) ){
            if( groupSelected ){
              groupPopupMenu.show(e.getComponent(), e.getX(), e.getY());
            } else {
              popupMenu.show(e.getComponent(), e.getX(), e.getY());
            }
          } else if( Config.left(e) ){
            if( e.isShiftDown() ){
              toggleGroupSelected();
            } else {
              draggedAtX = e.getX();
              draggedAtY = e.getY();
              if( ! isMovingDevices() ){
                JComponent jc = (JComponent)e.getSource();
                TransferHandler th = jc.getTransferHandler();
                th.exportAsDrag(jc, e, TransferHandler.COPY);
              }
            }
          }
        }
      };
      addMouseListener(ml);

      addMouseMotionListener(new MouseAdapter(){
        public void mouseDragged(MouseEvent e)
        {
          if( isMovingDevices() ){
            setLocation(e.getX() - draggedAtX + getLocation().x,
                e.getY() - draggedAtY + getLocation().y);
          }
        }
      });

    }
  }

  Long[] groupSelectedIds(){
    List<Long> list = new ArrayList<>();
    for( DevicePanel dp : devicePanels.values() ){
      if( dp.groupSelected ){
        list.add(dp.devId);
      }
    }
    return list.toArray(new Long[list.size()]);
  }

  void groupDeselectAll(){
    for( DevicePanel dp : devicePanels.values() ){
      if( dp.groupSelected ){
        dp.setGroupSelected(false);
      }
    }
  }


   /*
  void cleanupOtherlistsAfterDragDrop(JList dropTarget, Object[] valsDropped){
    for( JList list : conferenceLists.values() ){
      if( list != dropTarget ){
        DefaultListModel listModel = (DefaultListModel)list.getModel();
        for( Object o : valsDropped ){
          listModel.removeElement(o);
        }
      }
    }
  }
  */


}
